feat(share): point the app at a self-hosted share/collab server at runtime - #1687
Merged
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1684. First step of #1665's self-hosting track.
Problem
The web container could not be pointed at a self-hosted sharing server or collaboration relay.
resolveShareBaseUrl()andresolveCollabBaseUrl()already honoredVITE_GEOLIBRE_SHARE_URL/VITE_GEOLIBRE_COLLAB_URL— but both readimport.meta.env, so they were build-time only, and neither variable appeared inDockerfileordocker/entrypoint.sh. Repointing the published image meant forking and rebuilding it.There was also a worse failure mode.
resolveShareBaseUrl()fell back tohttps://share.geolibre.appwhenever the configured value failed to parse or was HTTP on a non-loopback host. A self-hosted deployment that sethttp://geolibre.lan:8080, or typo'd its own hostname, got a working Share button that uploaded its users' projects to the public hosted service.What changed
The entrypoint already writes
geolibre-runtime-config.json every boot (for the AI proxy and embed origins), so both hosts now flow through that same channel:lib/deployment-env.tsVITE_*value, deployment env before build env — the precedencereadEmbedOriginsandreadDeploymentAssistantEnvalready use.resolveShareHost()default/configured/disabled/invalid— plus the base URL and the configured value.resolveShareBaseUrl()is now a thin wrapper returningstring | null.GEOLIBRE_SHARE_URL=offresolveCollabBaseUrl()docker/entrypoint.shGEOLIBRE_EMBED_ORIGINSblock already applies.DockerfileARG/ENVpairs, so the build-time path is documented rather than accidental.No more silent fallback. A rejected value resolves to null; the hosted default applies only when nothing is configured. Menu entries disable with a reason, and the gallery throws a new
not-configuredGalleryErrorCode.The hostname is no longer hardcoded in the UI. 11 catalogue keys across all 16 locales now take a
{{shareHost}}interpolation (the hostname isn't translated, so this was a mechanical substitution), and the account-settings link inSettingsDialog/ShareProjectDialogderives from the resolved host. A self-hosted instance previously read "Sign in to share.geolibre.app" while linking somewhere else.TLS policy (decision on item 6 of the issue)
Kept as-is and now documented: HTTPS/WSS required, plaintext only on loopback. These URLs carry a Bearer token. The change is that a value failing this now fails the container boot with an error naming the variable, instead of quietly using the public service. Self-hosters put the server behind a TLS-terminating proxy. I did not add the
GEOLIBRE_SHARE_ALLOW_INSECUREescape hatch the issue floated — happy to if you'd rather have it.Verification
Beyond the unit tests, I drove the built web app under
vite previewwith the runtime config set four ways (clearing the service worker between each, since it precaches the config):share.geolibre.appoffhttp://internal.corparia-disabled=true, title "Unavailable: this deployment's sharing server address is not valid."https://maps.example.orghttps://maps.example.org/settingsAlso exercised the entrypoint's validator across 12 inputs —
https,off/OFF, loopbackhttp,wss, loopbackwsall accepted; plaintext LAN, unparseable, embedded credentials, and wrong-scheme all exit with a message naming the variable.Gate:
npm run build,npm run test:frontend(4959 pass / 0 fail),npm run test:worker,npm run lint(0 errors; the two TopToolbar warnings are pre-existing onmain, verified by stashing).Notes for review
resolveShareBaseUrl()changing fromstringtostring | nullis the deliberate core of this. Four call sites handle null; the tests that asserted the old fallback now assert refusal.installNativeShareFetchskips the override when null, but the Taurihttp:defaultcapability scope still pins the share host, so self-hosting stays a web/Docker capability. Called out inshare-fetch.tsand the docs.pre-commit runcould not install its node hook env locally (npm error Unknown cli flag: --ignore-prepublish— a toolchain issue on my machine, not this branch), so I ran the hook equivalents directly:oxfmt@0.59.0over every changed file, plus eslint and the build via the npm scripts. pre-commit.ci will run the rest on the PR.Summary by CodeRabbit
New Features
Bug Fixes
Documentation